package com.hlkj.pay.app.merchant.ext.impl.fuyou.utils;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

import com.hlkj.pay.app.merchant.ext.impl.fuyou.constant.FuYouConstant;

import cn.hutool.core.codec.Base64Decoder;
import cn.hutool.core.codec.Base64Encoder;


/**
 * Created by Ricky on 2016/11/19.
 */
public class Sign {

    /**
     * sign(RSA签名方法)
     * TODO(这里描述这个方法适用条件 – 可选)
     *
     * @param srcSignPacket
     * @param privateKey
     * @return String    DOM对象
     * @Exception 异常对象
     */
    public static String sign(String srcSignPacket, String privateKey)
            throws IOException, NoSuchAlgorithmException,
            InvalidKeySpecException, InvalidKeyException, SignatureException {
        // 解密由base64编码的私钥
        
        // byte[] bytesKey = (new BASE64Decoder()).decodeBuffer(privateKey);
        byte[] bytesKey = Base64Decoder.decode(privateKey.getBytes(StandardCharsets.UTF_8));
        // 构造PKCS8EncodedKeySpec对象
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(bytesKey);
        // KEY_ALGORITHM 指定的加密算法
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        // 取私钥匙对象
        PrivateKey priKey = keyFactory.generatePrivate(pkcs8KeySpec);
        // 用私钥对信息生成数字签名
        Signature signature = Signature.getInstance("MD5WithRSA");
        signature.initSign(priKey);
        signature.update(srcSignPacket.getBytes(FuYouConstant.charset));
        // String sign = (new BASE64Encoder()).encodeBuffer(signature.sign());
        String sign = Base64Encoder.encode(signature.sign());
        return sign;
    }

    /**
     * 校验数字签名
     *
     * @param data      加密数据
     * @param publicKey 公钥
     * @param sign      数字签名
     * @return 校验成功返回true 失败返回false
     * @throws Exception
     */
    public static boolean verify(byte[] data, String publicKey, String sign) throws Exception {

        // 解密由base64编码的公钥
        byte[] keyBytes = decryptBASE64(publicKey);

        // 构造X509EncodedKeySpec对象
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);

        // KEY_ALGORITHM 指定的加密算法
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");

        // 取公钥匙对象
        PublicKey pubKey = keyFactory.generatePublic(keySpec);

        Signature signature = Signature.getInstance("MD5withRSA");
        signature.initVerify(pubKey);
        signature.update(data);

        // 验证签名是否正常
        return signature.verify(decryptBASE64(sign));
    }

    /**
     * BASE64加密
     *
     * @param key
     * @return
     * @throws Exception
     */
    public static String encryptBASE64(byte[] key) throws Exception {
        // return (new BASE64Encoder()).encodeBuffer(key);
        
        Base64Encoder base64Encoder = new Base64Encoder();
        return base64Encoder.encode(key);
    }

    /**
     * BASE64解密
     *
     * @param key
     * @return
     * @throws Exception
     */
    public static byte[] decryptBASE64(String key) throws Exception {
        Base64Decoder encoder = new Base64Decoder();
        return encoder.decode(key);
    }

}
